package com.ndood.payment.core.oauth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

import com.ndood.payment.core.properties.PaymentProperties;

/**
 * 微信小程序授权服务器配置 加了这个等于把app定义成认证服务器。可以通过app获取token
 * 大致流程：
 * 1 小程序调用登录接口，后台到远程到微信获取openId，sessionKey，生成connection。静默方式注册一个用户，并进行认证成功
 * 2 认证成功处理器中生成根据inmemoryclientdetails生成一个token存入redis，并最终返回token.
 * 3 注意token的有效期必须设置的比sessionKey有效期短，这样小程序token失效可以重新调用登录接口，刷新sessionKey和token
 * 4 小程序端的refresh token无需使用，假设token失效了调用了refresh token，小程序检测到用户行为，也会延长sessionkey有效期
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private TokenStore tokenStore;

	@Autowired
	private PaymentProperties paymentProperties;
	
	/**
	 * 修改endpoints配置 TokenEndpoint是用来处理/oauth/token请求的入口
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		// 改造成redis持久化模式
		endpoints.tokenStore(tokenStore).authenticationManager(authenticationManager)
				.userDetailsService(userDetailsService);
	}

	/**
	 * 修改跟客户端相关的一些配置 我们的认证服务器会给哪些第三方应用发这些令牌
	 * clientDetails直接存内存中，只支持小程序
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
		builder
			.withClient(paymentProperties.getAuth().getClientId())
			.secret(paymentProperties.getAuth().getClientSecret())
			.accessTokenValiditySeconds(paymentProperties.getAuth().getExpireIn().intValue())
			.authorizedGrantTypes("refresh_token", "miniprogram")
			// 新增配置，设置refreshToken的有效时间 多给10分钟
			.refreshTokenValiditySeconds(paymentProperties.getAuth().getExpireIn().intValue() + 600); 
	}

}
